#include <iostream>
#include <memory>
#include "MysqlConn.hpp"
#include "ConnectionPool.hpp"
#include <thread>
using namespace std;

int query() {
	MysqlConn conn;
	conn.connect("scSQL_Linux", "1234", "connectForCppTest", "192.168.168.129");
	// 插入语句
	string sql = "INSERT INTO person VALUES(6, 36, 'man', 'curry')";
	bool flag = conn.update(sql);
	cout << "flag val: " << flag << endl;

	// 查询
	sql = "SELECT * FROM person";
	conn.query(sql);
	// 遍历结果集
	while (conn.next())
	{
		cout << conn.value(0) << ", " << conn.value(1) << ", " << conn.value(2) << ", " << conn.value(3) << endl;
	}
	return 0;
}

// 效率对比
// 1. 单线程  使用连接池/不使用
// 2. 多线程  使用连接池/不使用
void op1(int begin, int end) {
	for (int i = begin; i < end; i++) {
		// 线程执行op函数 创建 end - begin 个连接
		MysqlConn conn;
		conn.connect("scSQL_Linux", "1234", "connectForCppTest", "192.168.168.129");
		char sql[1024] = {0};
		sprintf(sql, "INSERT INTO person VALUES(%d, 36, 'man', 'curry')", i);
		conn.update(sql);
	}
}

void op2(ConnectionPool* pool, int begin, int end) {
	for (int i = begin; i < end; i++) {
		// 使用连接池 就不需要每次都创建新的连接  从创建好的队列中取出可用连接

		// 使用连接池 要使用连接池的实例对象
		shared_ptr<MysqlConn> conn = pool->getConnection();
		// 循环走完之后 共享智能指针对应的对象 conn 会析构   shared_ptr 提供默认删除器  
		// 默认删除器： 析构 MysqlConn 的内存地址
		// 删除器我们自定义了 就不会析构该内存地址 而是将该内存地址重新push进连接池对应的任务队列中
		// 外部的共享智能指针被析构  先将连接 进任务队列（也就进连接池）
		// 共享的智能指针被多个 shared_ptr 引用 ，管理内存是有一个引用计数的 计数变为0 就被回收（共享的智能指针对应的删除器才会被自动地调用）
		// 使用该对象对数据库进行操作 
		char sql[1024] = {0};
		sprintf(sql, "INSERT INTO person VALUES(%d, 36, 'man', 'curry')", i);
		conn->update(sql);
	}
}

// 单线程效率测试函数
void test1() {
#if 0
	// 非连接池，单线程，时长: 88363277403 纳秒，883632 毫秒
	// 两个时间点计时
	steady_clock::time_point begin = steady_clock::now();
	op1(0, 1000);
	steady_clock::time_point end = steady_clock::now();
	auto len = end - begin;
	cout << "非连接池，单线程，时长: " << len.count() << "纳秒，" << len.count() / 100000 << "毫秒" << endl;
#else 
	// 连接池，单线程，时长: 1509409140 纳秒，15094 毫秒
	ConnectionPool* pool = ConnectionPool::getConnectionPool();
	// 两个时间点计时
	std::chrono::steady_clock::time_point begin = std::chrono::steady_clock::now();
	op2(pool, 0, 1000);
	std::chrono::steady_clock::time_point end = std::chrono::steady_clock::now();
	auto len = end - begin;
	std::cout << "连接池，单线程，时长: " << len.count() << "纳秒，" << len.count() / 100000 << "毫秒" << endl;
#endif
}

void test2() {
#if 1
	// 非连接池，多线程，时长: 54424897979 纳秒，544248 毫秒
	// 两个时间点计时
	steady_clock::time_point begin = steady_clock::now();
	thread t1(op1, 0, 200);
	thread t2(op1, 200, 400);
	thread t3(op1, 400, 600);
	thread t4(op1, 600, 800);
	thread t5(op1, 800, 1000);
	t1.join();
	t2.join();
	t3.join();
	t4.join();
	t5.join();
	steady_clock::time_point end = steady_clock::now();
	auto len = end - begin;
	cout << "非连接池，多线程，时长: " << len.count() << " 纳秒，" << len.count() / 100000 << " 毫秒" << endl;
#else 
	// 连接池，多线程，时长: 1016954172 纳秒，10169 毫秒
	ConnectionPool* pool = ConnectionPool::getConnectionPool();
	// 两个时间点计时
	std::chrono::steady_clock::time_point begin = std::chrono::steady_clock::now();
	thread t1(op2, pool, 0, 200);
	thread t2(op2, pool, 200, 400);
	thread t3(op2, pool, 400, 600);
	thread t4(op2, pool, 600, 800);
	thread t5(op2, pool, 800, 1000);
	t1.join();
	t2.join();
	t3.join();
	t4.join();
	t5.join();
	std::chrono::steady_clock::time_point end = std::chrono::steady_clock::now();
	auto len = end - begin;
	std::cout << "连接池，多线程，时长: " << len.count() << " 纳秒，" << len.count() / 100000 << " 毫秒" << endl;
	#endif
}

int main(int argc, char const *argv[])
{
	// 单线程测试
	// test1();
	// 多线程测试
	test2();
	return 0;
}